#include <string.h>
#include <math.h>
#include "ml.h"

void mlZero2v(MLvec2 *vec){
	memset(vec, 0, sizeof(MLvec2));
}

void mlZero2m(MLmat2 *mat){
	memset(mat, 0, sizeof(MLmat2));
}

void mlZero3v(MLvec3 *vec){
	memset(vec, 0, sizeof(MLvec3));
}

void mlZero3m(MLmat3 *mat){
	memset(mat, 0, sizeof(MLmat3));
}

void mlZero4v(MLvec4 *vec){
	memset(vec, 0, sizeof(MLvec4));
}

void mlZero4m(MLmat4 *mat){
	memset(mat, 0, sizeof(MLmat4));
}

void mlVec2f(MLvec2 *vec, MLfloat *src){
	memcpy(vec->a, src, sizeof(MLvec2));
}

void mlVec2(MLvec2 *dst, MLvec2 *src){
	memcpy(dst->a, src->a, sizeof(MLvec2));
}

void mlVec3f(MLvec3 *vec, MLfloat *src){
	memcpy(vec->a, src, sizeof(MLvec3));
}

void mlVec3(MLvec3 *dst, MLvec3 *src){
	memcpy(dst->a, src->a, sizeof(MLvec3));
}

void mlVec4f(MLvec4 *vec, MLfloat *src){
	memcpy(vec->a, src, sizeof(MLvec4));
}

void mlVec4(MLvec4 *dst, MLvec4 *src){
	memcpy(dst->a, src->a, sizeof(MLvec4));
}

void mlIdentity2(MLmat2 *mat){
	mlZero2m(mat);
	mat->m[0][0] = 1.0f;
	mat->m[1][1] = 1.0f;
}

void mlMat2f(MLmat2 *mat, MLfloat *src){
	memcpy(mat->a, src, sizeof(MLmat2));
}

void mlMat2(MLmat2 *dst, MLmat2 *src){
	memcpy(dst->a, src->a, sizeof(MLmat2));
}

void mlIdentity3(MLmat3 *mat){
	mlZero3m(mat);
	mat->m[0][0] = 1.0f;
	mat->m[1][1] = 1.0f;
	mat->m[2][2] = 1.0f;
}

void mlMat3f(MLmat3 *mat, MLfloat *src){
	memcpy(mat->a, src, sizeof(MLmat3));
}

void mlMat3(MLmat3 *dst, MLmat3 *src){
	memcpy(dst->a, src->a, sizeof(MLmat3));
}

void mlIdentity4(MLmat4 *mat){
	mlZero4m(mat);
	mat->m[0][0] = 1.0f;
	mat->m[1][1] = 1.0f;
	mat->m[2][2] = 1.0f;
	mat->m[3][3] = 1.0f;
}

void mlMat4f(MLmat4 *mat, MLfloat *src){
	memcpy(mat->a, src, sizeof(MLmat4));
}

void mlMat4(MLmat4 *dst, MLmat4 *src){
	memcpy(dst->a, src->a, sizeof(MLmat4));
}

void mlVecNeg2(MLvec2 *vec){
	mlVecNeg2v(vec, vec);
}

void mlVecNeg2v(MLvec2 *dst, MLvec2 *src){
	dst->x = -(src->x);
	dst->y = -(src->y);
}

void mlVecNeg3(MLvec3 *vec){
	mlVecNeg3v(vec, vec);
}
void mlVecNeg3v(MLvec3 *dst, MLvec3 *src){
	dst->x = -(src->x);
	dst->y = -(src->y);
	dst->z = -(src->z);
}

void mlVecNeg4(MLvec4 *vec){
	mlVecNeg4v(vec, vec);
}
void mlVecNeg4v(MLvec4 *dst, MLvec4 *src){
	dst->x = -(src->x);
	dst->y = -(src->y);
	dst->z = -(src->z);
	dst->w = -(src->w);
}

void mlMatNeg2(MLmat2 *mat){
	mlMatNeg2m(mat, mat);
}
void mlMatNeg2m(MLmat2 *dst, MLmat2 *src){
	mlVecNeg2v(&(dst->v[0]), &(src->v[0]));
	mlVecNeg2v(&(dst->v[1]), &(src->v[1]));
}

void mlMatNeg3(MLmat3 *mat){
	mlMatNeg3m(mat, mat);
}
void mlMatNeg3m(MLmat3 *dst, MLmat3 *src){
	mlVecNeg3v(&(dst->v[0]), &(src->v[0]));
	mlVecNeg3v(&(dst->v[1]), &(src->v[1]));
	mlVecNeg3v(&(dst->v[2]), &(src->v[2]));
}

void mlMatNeg4(MLmat4 *mat){
	mlMatNeg4m(mat, mat);
}
void mlMatNeg4m(MLmat4 *dst, MLmat4 *src){
	mlVecNeg4v(&(dst->v[0]), &(src->v[0]));
	mlVecNeg4v(&(dst->v[1]), &(src->v[1]));
	mlVecNeg4v(&(dst->v[2]), &(src->v[2]));
	mlVecNeg4v(&(dst->v[3]), &(src->v[3]));
}

void mlVecAdd2(MLvec2 *vec, MLfloat val){
	mlVecAdd2f(vec, vec, val);
}
void mlVecAdd2f(MLvec2 *dst, MLvec2 *src, MLfloat val){
	dst->x = src->x + val;
	dst->y = src->y + val;
}
void mlVecAdd2v(MLvec2 *dst, MLvec2 *src1, MLvec2 *src2){
	dst->x = src1->x + src2->x;
	dst->y = src1->y + src2->y;
}
void mlMatAdd2(MLmat2 *mat, MLfloat val){
	mlMatAdd2f(mat, mat, val);
}
void mlMatAdd2f(MLmat2 *dst, MLmat2 *src, MLfloat val){
	mlVecAdd2f(&(dst->v[0]), &(src->v[0]), val);
	mlVecAdd2f(&(dst->v[1]), &(src->v[1]), val);
}
void mlMatAdd2m(MLmat2 *dst, MLmat2 *src1, MLmat2 *src2){
	mlVecAdd2v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecAdd2v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecAdd2v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
}

void mlVecAdd3(MLvec3 *vec, MLfloat val){
	mlVecAdd3f(vec, vec, val);
}
void mlVecAdd3f(MLvec3 *dst, MLvec3 *src, MLfloat val){
	dst->x = src->x + val;
	dst->y = src->y + val;
	dst->z = src->z + val;
}
void mlVecAdd3v(MLvec3 *dst, MLvec3 *src1, MLvec3 *src2){
	dst->x = src1->x + src2->x;
	dst->y = src1->y + src2->y;
	dst->z = src1->z + src2->z;
}
void mlMatAdd3(MLmat3 *mat, MLfloat val){
	mlMatAdd3f(mat, mat, val);
}
void mlMatAdd3f(MLmat3 *dst, MLmat3 *src, MLfloat val){
	mlVecAdd3f(&(dst->v[0]), &(src->v[0]), val);
	mlVecAdd3f(&(dst->v[1]), &(src->v[1]), val);
	mlVecAdd3f(&(dst->v[2]), &(src->v[2]), val);
}
void mlMatAdd3m(MLmat3 *dst, MLmat3 *src1, MLmat3 *src2){
	mlVecAdd3v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecAdd3v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecAdd3v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
}

void mlVecAdd4(MLvec4 *mat, MLfloat val){
	mlVecAdd4f(mat, mat, val);
}
void mlVecAdd4f(MLvec4 *dst, MLvec4 *src, MLfloat val){
	dst->x = src->x + val;
	dst->y = src->y + val;
	dst->z = src->z + val;
	dst->w = src->w + val;
}
void mlVecAdd4v(MLvec4 *dst, MLvec4 *src1, MLvec4 *src2){
	dst->x = src1->x + src2->x;
	dst->y = src1->y + src2->y;
	dst->z = src1->z + src2->z;
	dst->w = src1->w + src2->w;
}
void mlMatAdd4(MLmat4 *mat, MLfloat val){
	mlMatAdd4f(mat, mat, val);
}
void mlMatAdd4f(MLmat4 *dst, MLmat4 *src, MLfloat val){
	mlVecAdd4f(&(dst->v[0]), &(src->v[0]), val);
	mlVecAdd4f(&(dst->v[1]), &(src->v[1]), val);
	mlVecAdd4f(&(dst->v[2]), &(src->v[2]), val);
	mlVecAdd4f(&(dst->v[3]), &(src->v[3]), val);
}
void mlMatAdd4m(MLmat4 *dst, MLmat4 *src1, MLmat4 *src2){
	mlVecAdd4v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecAdd4v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecAdd4v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
	mlVecAdd4v(&(dst->v[3]), &(src1->v[3]), &(src2->v[3]));
}

void mlVecSub2(MLvec2 *vec, MLfloat val){
	mlVecSub2f(vec, vec, val);
}
void mlVecSub2f(MLvec2 *dst, MLvec2 *src, MLfloat val){
	dst->x = src->x - val;
	dst->y = src->y - val;
}
void mlVecSub2v(MLvec2 *dst, MLvec2 *src1, MLvec2 *src2){
	dst->x = src1->x - src2->x;
	dst->y = src1->y - src2->y;
}
void mlMatSub2(MLmat2 *mat, MLfloat val){
	mlMatSub2f(mat, mat, val);
}
void mlMatSub2f(MLmat2 *dst, MLmat2 *src, MLfloat val){
	mlVecSub2f(&(dst->v[0]), &(src->v[0]), val);
	mlVecSub2f(&(dst->v[1]), &(src->v[1]), val);
}
void mlMatSub2m(MLmat2 *dst, MLmat2 *src1, MLmat2 *src2){
	mlVecSub2v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecSub2v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecSub2v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
}

void mlVecSub3(MLvec3 *vec, MLfloat val){
	mlVecSub3f(vec, vec, val);
}
void mlVecSub3f(MLvec3 *dst, MLvec3 *src, MLfloat val){
	dst->x = src->x - val;
	dst->y = src->y - val;
	dst->z = src->z - val;
}
void mlVecSub3v(MLvec3 *dst, MLvec3 *src1, MLvec3 *src2){
	dst->x = src1->x - src2->x;
	dst->y = src1->y - src2->y;
	dst->z = src1->z - src2->z;
}
void mlMatSub3(MLmat3 *mat, MLfloat val){
	mlMatSub3f(mat, mat, val);
}
void mlMatSub3f(MLmat3 *dst, MLmat3 *src, MLfloat val){
	mlVecSub3f(&(dst->v[0]), &(src->v[0]), val);
	mlVecSub3f(&(dst->v[1]), &(src->v[1]), val);
	mlVecSub3f(&(dst->v[2]), &(src->v[2]), val);
}
void mlMatSub3m(MLmat3 *dst, MLmat3 *src1, MLmat3 *src2){
	mlVecSub3v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecSub3v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecSub3v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
}

void mlVecSub4(MLvec4 *mat, MLfloat val){
	mlVecSub4f(mat, mat, val);
}
void mlVecSub4f(MLvec4 *dst, MLvec4 *src, MLfloat val){
	dst->x = src->x - val;
	dst->y = src->y - val;
	dst->z = src->z - val;
	dst->w = src->w - val;
}
void mlVecSub4v(MLvec4 *dst, MLvec4 *src1, MLvec4 *src2){
	dst->x = src1->x - src2->x;
	dst->y = src1->y - src2->y;
	dst->z = src1->z - src2->z;
	dst->w = src1->w - src2->w;
}
void mlMatSub4(MLmat4 *mat, MLfloat val){
	mlMatSub4f(mat, mat, val);
}
void mlMatSub4f(MLmat4 *dst, MLmat4 *src, MLfloat val){
	mlVecSub4f(&(dst->v[0]), &(src->v[0]), val);
	mlVecSub4f(&(dst->v[1]), &(src->v[1]), val);
	mlVecSub4f(&(dst->v[2]), &(src->v[2]), val);
	mlVecSub4f(&(dst->v[3]), &(src->v[3]), val);
}
void mlMatSub4m(MLmat4 *dst, MLmat4 *src1, MLmat4 *src2){
	mlVecSub4v(&(dst->v[0]), &(src1->v[0]), &(src2->v[0]));
	mlVecSub4v(&(dst->v[1]), &(src1->v[1]), &(src2->v[1]));
	mlVecSub4v(&(dst->v[2]), &(src1->v[2]), &(src2->v[2]));
	mlVecSub4v(&(dst->v[3]), &(src1->v[3]), &(src2->v[3]));
}

#define _mlMatMul(a, b, c, n) \
	MLint i, j, k; \
	for(i = 0; i < n; i++) \
		for(j = 0; j < n; j++){ \
			a->m[j][i] = 0.0f; \
			for(k = 0; k < n; k++) \
				a->m[j][i] += b->m[k][i]*c->m[j][k]; \
		}

void mlMul2vf(MLvec2 *dst, MLvec2 *src, MLfloat val){
	dst->x = src->x * val;
	dst->y = src->y * val;
}
void mlMul2vm(MLvec2 *dst, MLvec2 *src_v, MLmat2 *src_m){
	dst->x = mlDot2(src_v, &(src_m->v[0]));
	dst->y = mlDot2(src_v, &(src_m->v[1]));
}
void mlMul2mv(MLvec2 *dst, MLmat2 *src_m, MLvec2 *src_v){
	dst->x = src_m->v[0].x*src_v->x + src_m->v[1].x*src_v->y;
	dst->y = src_m->v[0].y*src_v->x + src_m->v[1].y*src_v->y;
}
void mlMul2mf(MLmat2 *dst, MLmat2 *src, MLfloat val){
	mlMul2vf(&(dst->v[0]), &(src->v[0]), val);
	mlMul2vf(&(dst->v[1]), &(src->v[1]), val);
}
void mlMul2mm(MLmat2 *dst, MLmat2 *m1, MLmat2 *m2){
	if(dst != m1){
		_mlMatMul(dst, m1, m2, 2);
	}else{
		MLmat2 tmp;
		_mlMatMul((&tmp), m1, m2, 2);
		mlMat2(dst, &tmp);
	}
}
void mlMul3vf(MLvec3 *dst, MLvec3 *src, MLfloat val){
	dst->x = src->x * val;
	dst->y = src->y * val;
	dst->z = src->z * val;
}
void mlMul3vm(MLvec3 *dst, MLvec3 *src_v, MLmat3 *src_m){
	dst->x = mlDot3(src_v, &(src_m->v[0]));
	dst->y = mlDot3(src_v, &(src_m->v[1]));
	dst->z = mlDot3(src_v, &(src_m->v[2]));
}
void mlMul3mv(MLvec3 *dst, MLmat3 *src_m, MLvec3 *src_v){
	dst->x = src_m->v[0].x*src_v->x + src_m->v[1].x*src_v->y + src_m->v[2].x*src_v->z;
	dst->y = src_m->v[0].y*src_v->x + src_m->v[1].y*src_v->y + src_m->v[2].y*src_v->z;
	dst->z = src_m->v[0].z*src_v->x + src_m->v[1].z*src_v->y + src_m->v[2].z*src_v->z;
}
void mlMul3mf(MLmat3 *dst, MLmat3 *src, MLfloat val){
	mlMul3vf(&(dst->v[0]), &(src->v[0]), val);
	mlMul3vf(&(dst->v[1]), &(src->v[1]), val);
	mlMul3vf(&(dst->v[2]), &(src->v[2]), val);
}
void mlMul3mm(MLmat3 *dst, MLmat3 *m1, MLmat3 *m2){
	if(dst != m1){
		_mlMatMul(dst, m1, m2, 3);
	}else{
		MLmat3 tmp;
		_mlMatMul((&tmp), m1, m2, 3);
		mlMat3(dst, &tmp);
	}
}
void mlMul4vf(MLvec4 *dst, MLvec4 *src, MLfloat val){
	dst->x = src->x * val;
	dst->y = src->y * val;
	dst->z = src->z * val;
	dst->w = src->w * val;
}
void mlMul4vm(MLvec4 *dst, MLvec4 *src_v, MLmat4 *src_m){
	dst->x = mlDot4(src_v, &(src_m->v[0]));
	dst->y = mlDot4(src_v, &(src_m->v[1]));
	dst->z = mlDot4(src_v, &(src_m->v[2]));
	dst->w = mlDot4(src_v, &(src_m->v[3]));
}
void mlMul4mv(MLvec4 *dst, MLmat4 *src_m, MLvec4 *src_v){
	dst->x = src_m->v[0].x*src_v->x + src_m->v[1].x*src_v->y + src_m->v[2].x*src_v->z + src_m->v[3].x*src_v->w;
	dst->y = src_m->v[0].y*src_v->x + src_m->v[1].y*src_v->y + src_m->v[2].y*src_v->z + src_m->v[3].y*src_v->w;
	dst->z = src_m->v[0].z*src_v->x + src_m->v[1].z*src_v->y + src_m->v[2].z*src_v->z + src_m->v[3].z*src_v->w;
	dst->w = src_m->v[0].w*src_v->x + src_m->v[1].w*src_v->y + src_m->v[2].w*src_v->z + src_m->v[3].w*src_v->w;
}
void mlMul4mf(MLmat4 *dst, MLmat4 *src, MLfloat val){
	mlMul4vf(&(dst->v[0]), &(src->v[0]), val);
	mlMul4vf(&(dst->v[1]), &(src->v[1]), val);
	mlMul4vf(&(dst->v[2]), &(src->v[2]), val);
	mlMul4vf(&(dst->v[3]), &(src->v[3]), val);
}
void mlMul4mm(MLmat4 *dst, MLmat4 *m1, MLmat4 *m2){
	if(dst != m1){
		_mlMatMul(dst, m1, m2, 4);
	}else{
		MLmat4 tmp;
		_mlMatMul((&tmp), m1, m2, 4);
		mlMat4(dst, &tmp);
	}
}

MLfloat mlLength2(MLvec2 *vec){
	return sqrtf(vec->x*vec->x + vec->y*vec->y);
}
MLfloat mlLength3(MLvec3 *vec){
	return sqrtf(vec->x*vec->x + vec->y*vec->y + vec->z*vec->z);
}
MLfloat mlLength4(MLvec4 *vec){
	return sqrtf(vec->x*vec->x + vec->y*vec->y + vec->z*vec->z + vec->w*vec->w);
}

MLfloat mlDot2(MLvec2 *a, MLvec2 *b){
	return (a->x*b->x + a->y*b->y);
}
MLfloat mlDot3(MLvec3 *a, MLvec3 *b){
	return (a->x*b->x + a->y*b->y + a->z*b->z);
}
MLfloat mlDot4(MLvec4 *a, MLvec4 *b){
	return (a->x*b->x + a->y*b->y + a->z*b->z + a->w*b->w);
}

void mlReflect2(MLvec2 *inout, MLvec2 *n){
	mlReflect2v(inout, inout, n);
}
void mlReflect2v(MLvec2 *out, MLvec2 *in, MLvec2 *n){
	float dot = mlDot2(in, n)*2;
	mlMul2vf(out, n, dot);
	mlVecSub2v(out, in, out);
}
void mlReflect3(MLvec3 *inout, MLvec3 *n){
	mlReflect3v(inout, inout, n);
}
void mlReflect3v(MLvec3 *out, MLvec3 *in, MLvec3 *n){
	float dot = mlDot3(in, n)*2;
	mlMul3vf(out, n, dot);
	mlVecSub3v(out, in, out);
}
void mlReflect4(MLvec4 *inout, MLvec4 *n){
	mlReflect4v(inout, inout, n);
}
void mlReflect4v(MLvec4 *out, MLvec4 *in, MLvec4 *n){
	float dot = mlDot4(in, n)*2;
	mlMul4vf(out, n, dot);
	mlVecSub4v(out, in, out);
}

void mlCross(MLvec3 *c, MLvec3 *a, MLvec3 *b){
	c->a[0] = a->a[1]*b->a[2] - b->a[1]*a->a[2];
	c->a[1] = a->a[2]*b->a[0] - b->a[2]*a->a[0];
	c->a[2] = a->a[0]*b->a[1] - b->a[0]*a->a[1];
}

void mlNormalize2v(MLvec2 *dst, MLvec2 *src){
	float len = mlLength2(src);
	dst->x = src->x/len;
	dst->y = src->y/len;
}
void mlNormalize2(MLvec2 *vec){
	mlNormalize2v(vec, vec);
}
void mlNormalize3v(MLvec3 *dst, MLvec3 *src){
	float len = mlLength3(src);
	dst->x = src->x/len;
	dst->y = src->y/len;
	dst->z = src->z/len;
}
void mlNormalize3(MLvec3 *vec){
	mlNormalize3v(vec, vec);
}
void mlNormalize4v(MLvec4 *dst, MLvec4 *src){
	float len = mlLength4(src);
	dst->x = src->x/len;
	dst->y = src->y/len;
	dst->z = src->z/len;
	dst->w = src->w/len;
}
void mlNormalize4(MLvec4 *vec){
	mlNormalize4v(vec, vec);
}

#define _mlCompMul(a, b, c, n) \
	MLint i, j; \
	for(i = 0; i < n; i++) \
		for(j = 0; j < n; j++) \
			a->m[i][j] = b->m[i][j]*c->m[i][j];

void mlCompMul2(MLmat2 *dst, MLmat2 *m1, MLmat2 *m2){
	_mlCompMul(dst, m1, m2, 2);
}
void mlCompMul3(MLmat3 *dst, MLmat3 *m1, MLmat3 *m2){
	_mlCompMul(dst, m1, m2, 3);
}
void mlCompMul4(MLmat4 *dst, MLmat4 *m1, MLmat4 *m2){
	_mlCompMul(dst, m1, m2, 4);
}

#define _mlTranspose1(a, b, n) \
	MLint i, j; \
	for(i = 0; i < n; i++) \
		for(j = 0; j < n; j++) \
			a->m[i][j] = b->m[j][i];
void mlTranspose2m(MLmat2 *out, MLmat2 *in){
	_mlTranspose1(out, in, 2);
}
void mlTranspose3m(MLmat3 *out, MLmat3 *in){
	_mlTranspose1(out, in, 3);
}
void mlTranspose4m(MLmat4 *out, MLmat4 *in){
	_mlTranspose1(out, in, 4);
}


#define _mlTranspose2(a, n) \
	MLint i, j; \
	MLfloat tmp; \
	for(i = 0; i < n; i++) \
		for(j = 0; j <= i; j++){ \
			if(i == j) \
				continue; \
			tmp = a->m[j][i]; \
			a->m[j][i] = a->m[i][j]; \
			a->m[i][j] = tmp; \
		}
void mlTranspose2(MLmat2 *inout){
	_mlTranspose2(inout, 2);
}
void mlTranspose3(MLmat3 *inout){
	_mlTranspose2(inout, 3);
}
void mlTranspose4(MLmat4 *inout){
	_mlTranspose2(inout, 4);
}

void mlViewMat(MLmat4 *mat, MLvec3 *fv, MLvec3 *uv, MLvec3 *p){
	MLvec3 f, u, l;		/* forward, up, left */
	mlNormalize3v(&f, fv);
	mlNormalize3v(&u, uv);
	mlVecNeg3(&f);		/* camera's forward vector is -z direction */
	mlCross(&l, &u, &f);

	mat->v[0].x = l.x;	mat->v[1].x = l.y;	mat->v[2].x = l.z;	mat->v[3].x = -mlDot3(&l, p);
	mat->v[0].y = u.x;	mat->v[1].y = u.y;	mat->v[2].y = u.z;	mat->v[3].y = -mlDot3(&u, p);
	mat->v[0].z = f.x;	mat->v[1].z = f.y;	mat->v[2].z = f.z;	mat->v[3].z = -mlDot3(&f, p);
	mat->v[0].w = 0.0f;	mat->v[1].w = 0.0f;	mat->v[2].w = 0.0f;	mat->v[3].w = 1.0f;
}

void mlRotateXMat(MLmat4 *mat, MLfloat r){
	MLfloat sin_r = sinf(r);
	MLfloat cos_r = cosf(r);
	
	mlIdentity4(mat);
	mat->v[1].y = cos_r;	mat->v[2].y = -sin_r;
	mat->v[1].z = sin_r;	mat->v[2].z = cos_r;
}
void mlRotateYMat(MLmat4 *mat, MLfloat r){
	MLfloat sin_r = sinf(r);
	MLfloat cos_r = cosf(r);
	
	mlIdentity4(mat);
	mat->v[0].x = cos_r;	mat->v[2].x = sin_r;
	mat->v[0].z = -sin_r;	mat->v[2].z = cos_r;
}
void mlRotateZMat(MLmat4 *mat, MLfloat r){
	MLfloat sin_r = sinf(r);
	MLfloat cos_r = cosf(r);
	
	mlIdentity4(mat);
	mat->v[0].x = cos_r;	mat->v[1].x = -sin_r;
	mat->v[0].y = sin_r;	mat->v[1].y = cos_r;
}
void mlRotateAnyMat(MLmat4 *mat, MLvec3 *axis, MLfloat r){
}

void mlTranslateMat(MLmat4 *mat, MLvec3 *d){
	mlIdentity4(mat);
	mat->m[3][0] = d->x;
	mat->m[3][1] = d->y;
	mat->m[3][2] = d->z;
}
void mlProjMat(MLmat4 *prjMat, MLvec3 *lbn, MLvec3 *rtf, mlProjModes prjMode){
	MLfloat r_l = rtf->x - lbn->x;
	MLfloat t_b = rtf->y - lbn->y;
	MLfloat f_n = lbn->z - rtf->z;

	mlZero4m(prjMat);
	switch(prjMode){
		case ML_OTHOGONAL:
			prjMat->v[0].x = 2/r_l;

			prjMat->v[1].y = 2/t_b;

			prjMat->v[2].z = -2/f_n;
			
			prjMat->v[3].x = -(rtf->x + lbn->x)/r_l;
			prjMat->v[3].y = -(rtf->y + lbn->y)/t_b;
			prjMat->v[3].z = -(rtf->z + lbn->z)/f_n;
			prjMat->v[3].w = -1.0f;
			break;
		case ML_PERSPECTIVE:
		default:
			prjMat->v[0].x = (-2)*lbn->z/r_l;
			
			prjMat->v[1].y = (-2)*lbn->z/t_b;
			
			prjMat->v[2].x = (rtf->x + lbn->x)/r_l;
			prjMat->v[2].y = (rtf->y + lbn->y)/t_b;
			prjMat->v[2].z = (rtf->z + lbn->z)/f_n;
			prjMat->v[2].w = -1.0f;
			
			prjMat->v[3].z = -2*(rtf->z*lbn->z)/f_n;
			break;
	}
}
